#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

int lcd_fd;

void show_bmp(const char *, int, int);

int main(int argc, const char **agrv) {
  lcd_fd = open("/dev/fb0", O_RDWR);
  if (lcd_fd < 0) {
    perror("lcd open fail");
    exit(-1);
  }

  show_bmp("./cat.bmp", 0, 0);
  close(lcd_fd);
}

void show_bmp(const char *path, int x, int y) {
  int bmp_fd = open(path, O_RDONLY);
  if (bmp_fd < 0) {
    perror("bmp open fail");
    exit(-1);
  }
  lseek(bmp_fd, 18, SEEK_SET);
  int w, h;
  read(bmp_fd, &w, 4);
  read(bmp_fd, &h, 4);

  lseek(bmp_fd, 54, SEEK_SET);
  int w_a = w * 3 + (4 - w * 3 % 4) % 4;
  char rubbish[w_a * h];
  memset(rubbish, 0, sizeof(rubbish));
  read(bmp_fd, rubbish,sizeof(rubbish));

  printf("1\n");
  char bmp_buf[w * h * 3];
  for (int i = 0; i < h; i++) {
    memcpy(&bmp_buf[i * w * 3], &rubbish[w_a * i], w * 3);
  }
  printf("2\n");

  int *lcd_buf =
      mmap(NULL, 800 * 480 * 4, PROT_WRITE | PROT_READ, MAP_SHARED, lcd_fd, 0);
  for (int i = x; i < x + w; i++) {
    for (int j = y; j < y + h; j++) {
      lcd_buf[i + 800 * j] =
          bmp_buf[0 + 3 * (i - x + w * (h - 1 - (j - y)))] |
          bmp_buf[1 + 3 * (i - x + w * (h - 1 - (j - y)))] << 8 |
          bmp_buf[2 + 3 * (i - x + w * (h - 1 - (j - y)))] << 16 | 0;
    }
  }

  printf("3\n");

  munmap(lcd_buf, 800 * 480 * 4);
  close(bmp_fd);
}
